Lodash.concat 源码阅读

Author Avatar
Hongxu 2月 19, 2019

Lodash 源码阅读(四)

concat

该方法的效果同 Array.concat

var array = [1];
var other = _.concat(array, 2, [3], [[4]]);
console.log(array.concat(2, [3], [[4]])); // => [1, 2, 3, [4]]
console.log(other); // => [1, 2, 3, [4]]

import arrayPush from './_arrayPush.js';
import baseFlatten from './_baseFlatten.js';
import copyArray from './_copyArray.js';
import isArray from './isArray.js';

function concat() {
  var length = arguments.length;
  if (!length) {
    return [];
  }
  var args = Array(length - 1),
      array = arguments[0],
      index = length;

  while (index--) {
    args[index - 1] = arguments[index];
  }
  return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
}

工具函数

_arrayPush

param1: array

param2: values

两个参数均为数组,将第二个数组中每个值 push 到 第一个参数后面

使用示例
var array = [1, 2, 3, 4];
var values = [5, 6, 7, [8], "9"];
console.log(arrayPush(array, values)); // [1, 2, 3, 4, 5, 6, 7, [8], "9"]
源码
function arrayPush(array, values) {
  var index = -1,
      length = values.length,
      offset = array.length;
  // 循环将 values 里的值挨个放到 array 中并返回 array
  while (++index < length) {
    array[offset + index] = values[index];
  }
  return array;
}

_copyArray

param1: source 为待复制(浅复制)的数组

param2: array 为目标数组或为空

使用示例
copyArray([1, 2, 3]); // [1, 2, 3]
源码
function copyArray(source, array) {
  var index = -1,
      length = source.length;

  array || (array = Array(length));
  while (++index < length) {
    // 浅复制
    array[index] = source[index];
  }
  return array;
}

_baseFlatten

param1: array 想要扁平化的数组

param2: depth 扁平化的深度

param3: predicate 判断是否需要扁平化的函数

param4: isStrict

param5: result

使用示例
baseFlatten([1, [2], 3, [4, 5, [6, 7]]], 1); // [1, 2, 3, 4, 5, [6, 7]]
源码
import arrayPush from './_arrayPush.js';
import isFlattenable from './_isFlattenable.js';

function baseFlatten(array, depth, predicate, isStrict, result) {
  var index = -1,
      length = array.length;

  predicate || (predicate = isFlattenable);
  result || (result = []);

  while (++index < length) {
    var value = array[index];

    // 如果当前深度大于 0 且当前值是可以扁平化的
    if (depth > 0 && predicate(value)) {
      if (depth > 1) {
        // 递归去扁平化数组
        // Recursively flatten arrays (susceptible to call stack limits).
        baseFlatten(value, depth - 1, predicate, isStrict, result);
      } else {
        // depth === 1 时该函数完成了扁平化,进行赋值操作
        arrayPush(result, value);
      }
    } else if (!isStrict) { // 限制哪些没有通过扁平化测试的值,如果不是严格型的就赋值,如果是严格型的就丢弃
      result[result.length] = value;
    }
  }
  return result;
}

_isFlattenable

param1: value 待判断是否可以做扁平化操作的值

源码
import Symbol from './_Symbol.js';
import isArguments from './isArguments.js';
import isArray from './isArray.js';

/** Built-in value references. */
var spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;

function isFlattenable(value) {
  return isArray(value) || isArguments(value) ||
    !!(spreadableSymbol && value && value[spreadableSymbol]);
}